﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Odyssey.Classes;
using System.Linq;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Imaging;


namespace Odyssey.Controls
{
    /// <summary>
    /// Page animation with a transition from a list item to details and vice versa.
    /// </summary>
    public class FluidAnimation : PageAnimation
    {
        private ListBoxItem selectedItem;

        public FluidAnimation()
            : base()
        {
            ElementName = "PageTitle";
            DetailToYOffset = 340d;
        }

        public double DetailToYOffset { get; set; }

        /// <summary>
        /// Gets or sets the name of the element to be animated.
        /// </summary>
        public string ElementName { get; set; }

        public FluidMode Behavior { get; set; }


        protected override bool ShowOverride(Page page)
        {
            switch (Behavior)
            {
                case FluidMode.List: ShowToList(page); break;
                case FluidMode.Detail: ShowToDetail(page); break;
            }
            return true;
        }


        protected override bool HideOverride(Page page)
        {
            switch (Behavior)
            {
                case FluidMode.List: HideFromList(page); break;
                case FluidMode.Detail: HideFromDetail(page); break;
            }
            return true;
        }

        private void ShowToDetail(Page page)
        {
            page.Loaded += OnDetailPageLoaded;
            
            CompositeTransform transform = new CompositeTransform();
            page.RenderTransform = transform;
            Storyboard sb = GetClearStoryboard();
            Duration duration = this.Duration;
            var ease = new ExponentialEase { Exponent = 4, EasingMode = EasingMode.EaseOut };

            DoubleAnimation translateY = new DoubleAnimation
            {
                Duration = duration,
                To = 0d,
                From = 64d,
                EasingFunction = ease
            };
            Storyboard.SetTarget(translateY, page);
            Storyboard.SetTargetProperty(translateY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
            sb.Children.Add(translateY);

            FrameworkElement title = !string.IsNullOrEmpty(ElementName) ? page.FindName(ElementName) as FrameworkElement : (FrameworkElement)null;
            if (title != null)
            {
                CompositeTransform itemTranslate = new CompositeTransform();
                title.RenderTransform = itemTranslate;
                double w = page.ActualWidth * 0.8d;
                DoubleAnimation itemTranslateX = new DoubleAnimation
                {
                    Duration = duration,
                    From = w,
                    To = 0d,
                    EasingFunction = ease
                };
                Storyboard.SetTarget(itemTranslateX, title);
                Storyboard.SetTargetProperty(itemTranslateX, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)"));

                DoubleAnimation itemTranslateY = new DoubleAnimation
                {
                    Duration = duration,
                    From = -DetailToYOffset,
                    To = 0d,
                    EasingFunction = ease
                };
                Storyboard.SetTarget(itemTranslateY, title);
                Storyboard.SetTargetProperty(itemTranslateY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
                sb.Children.Add(itemTranslateX);
                sb.Children.Add(itemTranslateY);
            }
            //            sb.Begin();
        }

        void OnDetailPageLoaded(object sender, EventArgs e)
        {
            Page page = sender as Page;
            page.Loaded -= OnDetailPageLoaded;
            InternalStoryboard.Begin();
        }

        private void ShowToList(Page page)
        {
            page.Loaded += OnListPageLoaded;
            page.UpdateLayout();
            CompositeTransform transform = new CompositeTransform();
            page.RenderTransform = transform;
            Storyboard sb = GetClearStoryboard();
            Duration duration = this.Duration;
            var ease = new ExponentialEase { Exponent = 3, EasingMode = EasingMode.EaseOut };

            ListBoxItem item = selectedItem;
            selectedItem = null;
            if (item != null)
            {
                CompositeTransform itemTranslate = new CompositeTransform();
                item.RenderTransform = itemTranslate;
                DoubleAnimation itemTranslateX = new DoubleAnimation
                {
                    Duration = duration,
                    From = -128d,
                    To = 0d,
                    EasingFunction = ease
                };
                Storyboard.SetTarget(itemTranslateX, item);
                Storyboard.SetTargetProperty(itemTranslateX, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)"));

                DoubleAnimation itemTranslateY = new DoubleAnimation
                {
                    Duration = duration,
                    From = -32d,
                    To = 0d,
                    EasingFunction = ease
                };
                Storyboard.SetTarget(itemTranslateY, item);
                Storyboard.SetTargetProperty(itemTranslateY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
                sb.Children.Add(itemTranslateX);
                sb.Children.Add(itemTranslateY);
                sb.Completed += (s, e) => item.RenderTransform = null;
            }

            sb.Begin();
        }

        private void HideFromDetail(Page page)
        {
            CompositeTransform transform = new CompositeTransform();
            page.RenderTransform = transform;
            Storyboard sb = GetClearStoryboard();
            Duration duration = this.Duration;
            var ease = new ExponentialEase { Exponent = 4, EasingMode = EasingMode.EaseIn };

            DoubleAnimation opacity = new DoubleAnimation
            {
                Duration = duration,
                To = 0d,
                EasingFunction = ease,
            };
            Storyboard.SetTarget(opacity, page);
            Storyboard.SetTargetProperty(opacity, new PropertyPath("Opacity"));
            sb.Children.Add(opacity);

            DoubleAnimation translateY = new DoubleAnimation
            {
                Duration = duration,
                To = 64d,
                EasingFunction = ease
            };
            Storyboard.SetTarget(translateY, page);
            Storyboard.SetTargetProperty(translateY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
            sb.Children.Add(translateY);
            sb.Begin();
        }

        private void HideFromList(Page page)
        {
            CompositeTransform transform = new CompositeTransform();
            page.RenderTransform = transform;
            Storyboard sb = GetClearStoryboard();
            Duration duration = this.Duration;
            var ease = new ExponentialEase { Exponent = 4, EasingMode = EasingMode.EaseIn };

            DoubleAnimation opacity = new DoubleAnimation
            {
                Duration = duration,
                To = 0d,
                EasingFunction = ease,
            };
            Storyboard.SetTarget(opacity, page);
            Storyboard.SetTargetProperty(opacity, new PropertyPath("Opacity"));
            sb.Children.Add(opacity);

            DoubleAnimation translateY = new DoubleAnimation
            {
                Duration = duration,
                To = 64d,
                EasingFunction = ease
            };
            Storyboard.SetTarget(translateY, page);
            Storyboard.SetTargetProperty(translateY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
            sb.Children.Add(translateY);

            ListBox listBox = page.GetVisualDescendants().OfType<ListBox>().FirstOrDefault();
            if (listBox != null && listBox.SelectedIndex >= 0)
            {

                ListBoxItem item = listBox.ItemContainerGenerator.ContainerFromIndex(listBox.SelectedIndex) as ListBoxItem;
                if (item != null)
                {
                    UIElement element = (!string.IsNullOrEmpty(ElementName)) ? item.FindVisualChild(ElementName) as UIElement : null;
                    if (element == null) element = item;
                    selectedItem = item;
                    FrameworkElement rootElement = page.GetVisualChild(0);
                    Popup popup = new Popup();

                    Point point = element.TransformToVisual(rootElement).Transform(new Point());
                    popup.VerticalOffset = point.Y;
                    popup.HorizontalOffset = point.X;


                    WriteableBitmap bm = new WriteableBitmap(element, null);
                    bm.Invalidate();
                    Image image = new Image { Source = bm, Stretch = System.Windows.Media.Stretch.None };
                    popup.Child = image;


                    DoubleAnimation itemOpacity = new DoubleAnimation
                    {
                        Duration = TimeSpan.FromMilliseconds(0),
                        To = 0d
                    };
                    Storyboard.SetTarget(itemOpacity, item);
                    Storyboard.SetTargetProperty(itemOpacity, new PropertyPath("Opacity"));
                    sb.Children.Add(itemOpacity);

                    //  listBox.SelectedItem = null;
                    CompositeTransform itemTranslate = new CompositeTransform();
                    double w = listBox.ActualWidth * 0.8d;
                    popup.RenderTransform = itemTranslate;
                    DoubleAnimation itemTranslateX = new DoubleAnimation
                    {
                        Duration = duration,
                        To = w,
                        EasingFunction = ease
                    };
                    Storyboard.SetTarget(itemTranslateX, popup);
                    Storyboard.SetTargetProperty(itemTranslateX, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateX)"));

                    DoubleAnimation itemTranslateY = new DoubleAnimation
                    {
                        Duration = duration,
                        To = 70d,
                        EasingFunction = ease
                    };
                    Storyboard.SetTarget(itemTranslateY, popup);
                    Storyboard.SetTargetProperty(itemTranslateY, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
                    sb.Children.Add(itemTranslateX);
                    sb.Children.Add(itemTranslateY);
                    popup.IsOpen = true;
                    sb.Completed += (s, e) => popup.IsOpen = false;
                }
            }

            sb.Begin();
        }

        void OnListPageLoaded(object sender, EventArgs e)
        {
            Page page = sender as Page;
            page.Loaded -= OnListPageLoaded;
            InternalStoryboard.Begin();
        }
    }
}
